import axios from 'axios';

import {
	GetFleetResponse,
	GetGraphResponse,
	GetIceCoverForecastDatesResponse,
	GetIceCoverResponse,
	GetPlannerStateResponse,
	GetRoutesResponse
} from './';


const enum Method {
	GET = 'get',
	POST = 'post',
	DELETE = 'delete',
}


class Api {
	private active_requests = 0;


	constructor() { }


	private async makeRequest<T = undefined>(_url: string, method: Method, body: object = {}, query: Record<string, string> = {}) {
		return new Promise((resolve, reject) => {
			this.active_requests++;
			document.body.style.cursor = 'wait';

			const url = new URL(_url, axios.defaults.baseURL);

			Object.keys(query).forEach(key => {
				url.searchParams.set(key, query[key]);
			});

			axios[method](
				url.toString(),
				body
			).then(resposne => {
				resolve(resposne.data as T);
			}).catch(() => {
				reject();
			}).finally(() => {
				this.active_requests--;

				if (this.active_requests === 0)
					document.body.style.cursor = 'default';
			});
		}) as Promise<T>;
	}


	async getFleet() {
		return this.makeRequest<GetFleetResponse>('/fleet', Method.GET);
	}


	async getGraph() {
		return this.makeRequest<GetGraphResponse>('/planner/graph', Method.GET);
	}


	async sendIntegrVelocity(form_data: FormData) {
		return this.makeRequest('/ice', Method.POST, form_data);
	}


	async sendGraph(form_data: FormData) {
		return this.makeRequest('/planner/graph', Method.POST, form_data);
	}


	async sendFleet(form_data: FormData) {
		return this.makeRequest('/fleet', Method.POST, form_data);
	}


	async getPlannerState() {
		return this.makeRequest<GetPlannerStateResponse>('/planner/state', Method.GET);
	}


	async getRoutes() {
		return this.makeRequest<GetRoutesResponse>('/planner/routes', Method.GET);
	}


	async getDateList() {
		return this.makeRequest<GetIceCoverForecastDatesResponse>('/ice/dates', Method.GET);
	}

	async getIce(date: string) {
		return this.makeRequest<GetIceCoverResponse>('/ice', Method.GET, {}, { date });
	}
}


export const api = new Api();